package com.run_java_test.test4;

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;

@Component
public class ExternalControllerLoader {

    private final DefaultListableBeanFactory beanFactory;
    private final RequestMappingHandlerMapping handlerMapping;

    public ExternalControllerLoader(ApplicationContext applicationContext, RequestMappingHandlerMapping handlerMapping) {
        this.beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory();
        this.handlerMapping = handlerMapping;
    }

    /**
     * 动态注册 Controller
     *
     * @param beanName     Bean 的名称
     * @param javaFilePath Java 文件的路径
     * @throws Exception 编译或加载失败时抛出异常
     */
    public void registerController(String beanName, String javaFilePath) throws Exception {
        // 编译 Java 文件
        File javaFile = new File(javaFilePath);
        if (!javaFile.exists()) {
            throw new IllegalArgumentException("Java 文件不存在: " + javaFilePath);
        }

        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int result = compiler.run(null, null, null, javaFile.getPath());
        if (result != 0) {
            throw new IllegalStateException("Java 文件编译失败: " + javaFilePath);
        }

        // 加载编译后的类
        String classPath = javaFile.getParent(); // 编译文件所在目录
        String className = extractClassName(javaFilePath); // 提取类的全限定名
        URLClassLoader classLoader = new URLClassLoader(new URL[]{new File(classPath).toURI().toURL()});
        Class<?> controllerClass = classLoader.loadClass("com.run_java_test.test4.TemporaryController");

        // 动态注册为 Spring Bean
        if (beanFactory.containsBeanDefinition(beanName)) {
            throw new IllegalArgumentException("Bean 名称已存在: " + beanName);
        }

        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(controllerClass);
        beanDefinition.setScope("singleton");
        beanFactory.registerBeanDefinition(beanName, beanDefinition);

        // 手动刷新 HandlerMapping
        Object controllerBean = beanFactory.getBean(beanName);
        handlerMapping.afterPropertiesSet();
    }

    /**
     * 动态卸载 Controller
     *
     * @param beanName Bean 的名称
     */
    public void unregisterController(String beanName) {
        if (!beanFactory.containsBeanDefinition(beanName)) {
            throw new IllegalArgumentException("Bean 名称不存在: " + beanName);
        }

        beanFactory.removeBeanDefinition(beanName);

        // 刷新 HandlerMapping，移除路由
        handlerMapping.afterPropertiesSet();
    }

    /**
     * 提取类的全限定名（包名+类名）
     *
     * @param javaFilePath Java 文件路径
     * @return 全限定名
     */
    private String extractClassName(String javaFilePath) throws Exception {
        File file = new File(javaFilePath);
        String fileName = file.getName().replace(".java", "");
        String parentDir = file.getParentFile().getAbsolutePath(); // 文件的父目录

        // 假设基础目录为 D:/test
        String baseDir = "D:\\test\\";
        if (!parentDir.startsWith(baseDir)) {
            throw new IllegalArgumentException("Java 文件不在指定的基础目录下: " + baseDir);
        }

        // 提取包名部分
        String packagePath = parentDir.substring(baseDir.length() + 1); // 跳过基础目录部分
        String packageName = packagePath.replace(File.separator, "."); // 将路径转换为包名格式

        return packageName + "." + fileName; // 拼接完整类名
    }

}
